package com.twu.library;

import com.twu.library.model.Book;
import com.twu.library.model.Movie;
import com.twu.library.model.User;
import org.apache.commons.lang3.StringUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;

public class LibraryApp {

    private ArrayList<Book> listBooks;
    private BufferedReader reader;
    private int numberOption;
    private ArrayList<Movie> listMovie;
    private ArrayList<User> listUser;
    private int indexUser;

    public static void main(String[] args) {
        LibraryApp library = new LibraryApp();
        library.run();
    }

    public void run(){
        initializeTheProgram();
        manageMainMenu();
    }

    private void initializeTheProgram(){
        System.out.println("Welcome to Library App!");
        initializeListsAndVariables();
    }

    private void initializeListsAndVariables() {
        initializeReader();
        loadBookList();
        loadMovieList();
        loadUserList();
    }

    private void initializeReader(){
       if(reader == null)
            reader = new BufferedReader(new InputStreamReader(System.in));
    }

    private void manageMainMenu(){
        showMainMenu();
        waitForChoice();
        treatChoiceInMainMenu();
    }

    private void loadUserList() {
        if(listUser == null) {
            listUser = new ArrayList<User>();
            listUser.add(new User("000-0001","1234","Roselma Mendes","rmendes@thoughtworks.com","Rua Francisco da Cunha Recife PE","3333-7890"));
            listUser.add(new User("000-0002","0987","Marcondes Silva","msilva@thoughtworks.com","Rua do Recife","8901-6789"));
        }
    }

    private void showMainMenu() {
        System.out.println("Main Menu");
        System.out.println("#1 - List Books");
        System.out.println("#2 - Return Book");
        System.out.println("#3 - List Movies");
        System.out.println("#4 - User Information");
        System.out.println("Type the number that match with the option you wish[0 - Quit]:");
    }

    private void treatChoiceInMainMenu() {
        switch (numberOption){
            case 4:
                manageUserInformation();
                break;
            case 3:
                manageMovieList();
                break;
            case 2:
                manageReturnBookMenu();
                break;
            case 1:
                manageBookList();
                break;
            case 0:
                System.out.println("Finished Program.");
                break;
            default:
                System.out.println("Select a valid option!");
                waitForChoice();
                treatChoiceInMainMenu();
                break;
        }
    }

    private void manageUserInformation() {
        if(validUser()) {
            showUserInformation();
            waitForChoice();
            treatChoiceOnUserInformation();
        }
        else{
            System.out.println("Invalid User! Choose from Main Menu by User Information and try again.");
            manageMainMenu();
        }
    }

    private void showUserInformation() {
        User user = listUser.get(indexUser);
        System.out.println("Library Number: " + user.getLibraryNumber()  + " / User Name: " + user.getName() + "\nEmail: " + user.getEmail() + " / Address: " + user.getAddress() + " / Phone Number: " + user.getPhoneNumber());
        System.out.println("0 - Back to Main Menu.");
    }

    private void treatChoiceOnUserInformation() {
        switch(numberOption){
            case 0:
                manageMainMenu();
                break;
            default:
                System.out.println("Select a valid option!");
                waitForChoice();
                treatChoiceOnUserInformation();
                break;
        }
    }

    private void manageMovieList() {
        showMovieList();
        waitForChoice();
        treatChoiceOnMovieList();
    }

    private void showMovieList(){
        int tam = listMovie.size();
        Movie movie;
        for(int i = 0 ; i < tam ; i++) {
            movie = listMovie.get(i);
            if(!movie.isCheckout())
                System.out.println("#" + (i+1) + " - Name: " + movie.getName() + " - Year: " + movie.getYear() + " - Director: " + movie.getDirector() +
                    " - Rating: " + movie.getRating());
        }
        System.out.println("Type the number of the movie what you want to check out [0 - back to Main Menu]:");
    }

    private void loadMovieList(){
        if(listMovie == null) {
            listMovie = new ArrayList();
            listMovie.add(new Movie("After Earth","2013","M. Night Shyamalan","5",false));
            listMovie.add(new Movie("The Pursuit of Happiness","2006"," Gabriele Muccino","7.9",false));
            listMovie.add(new Movie("I Am Legend","2007"," Francis Lawrence","7.2",false));
            listMovie.add(new Movie("Men In Black","1997","Barry Sonnenfeld","7.2",false));
            listMovie.add(new Movie("Independence Day","1996","Roland Emmerich","6.9",false));
            listMovie.add(new Movie("Hancock","2008","Peter Berg","6.5",false));
            listMovie.add(new Movie("Hitch","2005","Peter Berg","6.5",false));
            listMovie.add(new Movie("Seven Pounds","2008","Gabriele Muccino","7.7",false));
            listMovie.add(new Movie("I, Robot","2004","Alex Proyas","7.1",false));
            listMovie.add(new Movie("Wild Wild West","1999","Barry Sonnenfeld","4.8",false));
        }
    }

    private void treatChoiceOnMovieList(){
        switch(numberOption) {
            case 0:
                manageMainMenu();
                break;
            default:
                if(listMovie.size() > numberOption && numberOption > 0) {
                    listMovie.get(numberOption - 1).setCheckout(true);
                    System.out.println("Thank you! Enjoy the movie.");
                    manageMovieList();
                }
                else{
                    System.out.println("Select a valid option!");
                    waitForChoice();
                    treatChoiceOnMovieList();
                }
                break;
        }
    }

    private void manageBookList(){
        showBookList();
        waitForChoice();
        treatChoiceInBookList();
    }

    private void showBookList() {
        int tam = listBooks.size();
        Book book;
        for(int i = 0 ; i < tam ; i++){
            book = listBooks.get(i);
            if(!book.isCheckout())
                System.out.println("#"+(i+1)+" - Title: " + book.getTitle() + " - Author: " + book.getAuthor()
                    + " - Year: " + book.getYear());
        }
        System.out.println("Type the number of the book what you want to check out [0 - back to Main Menu]:");
    }

    private void loadBookList() {
        if (listBooks == null){
            listBooks = new ArrayList();
            listBooks.add(new Book("Leviathan", "Westerfeld, Scott ", "2009", false, true));
            listBooks.add(new Book("Sparkling Cyanide", "Christie, Agatha", "2002", false, false));
            listBooks.add(new Book("As Esganadas", "Soares, Jô", "2011", false, true));
            listBooks.add(new Book("The High Queen", "Bradley, Marion Zimmer", "1993", false, true));
            listBooks.add(new Book("Iracema", "Alencar, Jose", "2005", false, true));
            listBooks.add(new Book("The Hobbit", "Tolkien, J. R. R.", "2002", false, true));
            listBooks.add(new Book("The Vampire Diaries The Awakening", "Smith, L. J.", "1999", false, true));
            listBooks.add(new Book("Murder On The Orient Express", "Christie, Agatha", "2004", false, true));
            listBooks.add(new Book("The Lightning Thief", "Riordan, Rick", "2006", false, true));
            listBooks.add(new Book("The Sea Of Monsters", "Riordan, Rick", "2006", false, true));
        }
    }

    private void treatChoiceInBookList() {
        switch (numberOption){
            case 0:
                manageMainMenu();
                break;
            default:
                if(numberOption >= 1) {
                    makeCheckoutOfTheBook();
                }
                else {
                    System.out.println("Select a valid option!");
                    waitForChoice();
                    treatChoiceInBookList();
                }
                break;
        }
    }

    private void makeCheckoutOfTheBook() {
        Book book = numberOption > listBooks.size()?
                    new Book("","","",false,false):
                    listBooks.get(numberOption - 1);
        if (book.isAvailable()) {
            if(validUser()) {
                book.setCheckout(true);
                book.setLibraryNumber(listUser.get(indexUser).getLibraryNumber());
                System.out.println("User: " + book.getLibraryNumber() + ", Thank you! Enjoy the book.");
                manageBookList();
            }
            else{
                System.out.println("Library Number And/Or Password wrong! Try Again.");
                manageBookList();
            }
        } else {
            System.out.println("That book is not available.");
            waitForChoice();
            treatChoiceInBookList();
        }

    }

    private boolean validUser() {
        String login = "",password = "";
        try {
            System.out.println("Library Number:");
            login = reader.readLine();
            System.out.println("Password:");
            password = reader.readLine();
        }
        catch(IOException e){
            e.printStackTrace();
        }
        return searchAndValid(login,password);
    }

    private boolean searchAndValid(String login, String password) {
        User user;
        for(int i = 0 ; i < listUser.size() ; i++){
            user = listUser.get(i);
            if(user.getLibraryNumber().equals(login) && user.getPassword().equals(password)) {
                indexUser = i;
                return true;
            }
        }
        return false;
    }

    private void manageReturnBookMenu(){
        showReturnBookMenu();
        waitForChoice();
        treatChoiceInReturnBookMenu();
    }

    private void showReturnBookMenu() {
        System.out.println("Type the number of the book to be returned [0 - back to Main Menu]:");
    }

    private void treatChoiceInReturnBookMenu() {
        switch(numberOption) {
            case 0:
                manageMainMenu();
                break;
            default:
                Book book = new Book("","","",false,false);
                boolean userPassed = false;
                if (listBooks.size() > (numberOption-1) && numberOption > 0) {
                    book = listBooks.get(numberOption - 1);
                    userPassed = makeTheReturnOfBook(book, userPassed);
                }
                if(!book.isCheckout() && !userPassed){
                    System.out.println(numberOption == -1 ?
                            "Select a valid option!":
                            "That is not a valid book to return.");
                    waitForChoice();
                    treatChoiceInReturnBookMenu();
                }
                break;
        }
    }

    private boolean makeTheReturnOfBook(Book book, boolean userPassed) {
        if(book.isCheckout()) {
            userPassed = validUser();
            if(userPassed) {
                book.setCheckout(false);
                System.out.println("Thank you for returning the book.");
                manageMainMenu();
            }
            else{
                System.out.println("Library Number And/Or Password wrong! Try Again.");
                manageReturnBookMenu();
            }
        }
        return userPassed;
    }

    private void waitForChoice(){
        try {
            String numberOptionStr = reader.readLine();
            if(StringUtils.isNumeric(numberOptionStr.subSequence(0,numberOptionStr.length())))
                numberOption = Integer.parseInt(numberOptionStr);
            else
                numberOption = -1;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
